home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mntlib43
/
mntlib
/
popen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-02
|
3KB
|
126 lines
/* popen(): open a file handle to a process. Works only under MiNT.
* Written by Eric R. Smith, based on the TOS version by Kai-Uwe Bloem.
*/
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#ifdef __TURBOC__
#include <sys\types.h>
#else
#include <sys/types.h>
#endif
#include <wait.h>
#include <mintbind.h>
struct _pipe {
int pid; /* process id of child */
FILE *pfile; /* created file descriptor */
struct _pipe *pnext; /* next pipe in the list. */
};
static struct _pipe *__pipes = NULL; /* head of pipe list */
FILE *popen(command, type)
const char *command, *type;
{
struct _pipe *p; /* the new pipe's list entry */
short pipfd[2]; /* pipe file handles */
int savefd; /* saved file descriptor for parent */
int kidfd; /* file descriptor changed in child */
/* 1 for "r", 0 for "w" */
char *shell;
FILE *pipefile = 0;
extern int __mint;
long r;
if (__mint == 0) {
errno = EINVAL;
return (FILE *)0;
}
shell = getenv("SHELL");
if (!shell)
shell = "sh";
/* get space for the new pipe. If we can't get it then that's that */
p = (struct _pipe *) malloc(sizeof(struct _pipe));
if (p == NULL) return (FILE *)0;
/* initialize the new pipe entry */
kidfd = (*type == 'r') ? 1 : 0;
r = Fdup (kidfd);
savefd = (int) r;
/* get those close-on-exec flags right...
(well just do fork/exec would be easier :-) -nox */
if (r < 0 || (r = Fcntl (savefd, 1L, F_SETFD)) < 0 ||
(r = Fpipe(pipfd)) < 0) { /* can't create pipe?? */
free(p);
errno = (int) -r;
return (FILE *)0;
}
/* other side of the pipe should be closed in the child */
(void) Fcntl(pipfd[1 - kidfd], (long) 1, F_SETFD);
Fforce(kidfd, pipfd[kidfd]);
Fclose(pipfd[kidfd]);
p->pid = spawnlp(P_NOWAIT, shell, shell, "-c", command, (char *)0);
Fforce(kidfd, savefd);
Fclose(savefd);
if (p->pid > 0) { /* command ran all right */
/* note: 1-kidfd tells us which handle to use in the parent */
pipefile = fdopen(pipfd[1 - kidfd], type);
}
if (pipefile) {
p->pfile = pipefile;
p->pnext = __pipes;
__pipes = p;
}
else {
/* carefully release all resources */
Fclose (pipfd[1 - kidfd]);
if (p->pid > 0) /* just in case... */
waitpid (p->pid, (int *) NULL, 0);
free(p);
}
return pipefile;
}
/* close a pipe created by popen().
*/
int pclose(fp)
FILE *fp;
{
struct _pipe *p, /* the pipe's list element */
**q; /* predecessor of p in the list */
int status = -1; /* return status of the command */
/* search the pipe list for a pipe matching the FILE descriptor */
for (p = __pipes, q = &__pipes; p && p->pfile != fp;
q = &p->pnext, p = p->pnext);
if (p == NULL) /* Never had a popen() for this file... */
return status; /* this pclose call makes no sense ! */
fclose(p->pfile); /* close the connection */
/* now wait for the command to finish */
waitpid (p->pid, &status, 0);
/* remove the pipe from the list */
*q = p->pnext;
/* Now free the pipe entry */
free(p);
return status;
}